package ref

import (
	"encoding/json"
	"errors"
	"fmt"
	"db2s/go-log/log"
	"os"
	"reflect"
	"runtime"
	"runtime/pprof"
	"sort"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

var MyWait sync.WaitGroup
var myWaitCount int64
var myWaitGroup = &myWaitCount
var myWaitWaitRecord = make(map[string]int)
var recordAdd, recordDel chan string

func MyWaitInit() {
	recordAdd = make(chan string, 10000000)
	recordDel = make(chan string, 10000000)
}
func MyWaitAdd(record string) {
	recordAdd <- record
	atomic.AddInt64(myWaitGroup, 1)
	MyWait.Add(1)
}
func MyWaitDel(record string) {
	recordDel <- record
	atomic.AddInt64(myWaitGroup, -1)
	MyWait.Done()
}
func MyWaitWait() {
	PrintMyWaitSum()
	MyWait.Wait()
}
func MyWaitClose() {
	close(recordAdd)
	close(recordDel)
}
func monitorMyWaitSum() {
	var addOpen = true
	var delOpen = true
	var mu sync.Mutex
	for {
		select {
		case c, ok := <-recordAdd:
			if ok {
				mu.Lock() // 加锁
				myWaitWaitRecord[c]++
				mu.Unlock() // 解锁
			} else {
				addOpen = false
			}
		case c, ok := <-recordDel:
			if ok {
				mu.Lock() // 加锁
				myWaitWaitRecord[c]--
				mu.Unlock() // 解锁
			} else {
				delOpen = false
			}
		}
		if !addOpen && !delOpen {
			log.MainLog().Info("[monitorMyWaitSum]", "quit MyWaitSum monitor !!!")
			return // 如果两个通道都关闭，则退出循环
		}
	}
}
func PrintMyWaitSum() {
	func() {
		monitorMyWaitSum()
		for {
			if atomic.LoadInt64(myWaitGroup) == 0 {
				log.MainLog().Info("[PrintMyWaitSum]", "normal quit Print MyWaitSum!!!")
				return
			}
			time.Sleep(time.Second)
			for k, v := range myWaitWaitRecord {
				if v == 0 {
					continue
				}
				log.MainLog().Warn("[PrintMyWaitSum]", fmt.Sprintf(" MyWaitSum:total wait:%v sub wait event:%v sub wait sum:%v", atomic.LoadInt64(myWaitGroup), k, v))
				fmt.Println(fmt.Sprintf("-----MyWaitSum:total wait:%v sub wait event:%v sub wait sum:%v", atomic.LoadInt64(myWaitGroup), k, v))
			}
		}
	}()
}
func MapValueReverseSort(data map[string]int64) (result []string) {
	// 创建一个切片来存储 map 的键
	keys := make([]string, 0, len(data))
	for k := range data {
		keys = append(keys, k)
	}
	// 按照对应的值进行倒序排序
	sort.Slice(keys, func(i, j int) bool {
		return data[keys[i]] > data[keys[j]]
	})

	// 创建一个切片来存储排序后的字符串
	result = make([]string, 0, len(data))
	for _, k := range keys {
		result = append(result, k)
	}
	return
}
func MapValueSort(data map[string]any) (result []string) {
	// 创建一个切片来存储 map 的键
	keys := make([]string, 0, len(data))
	for k := range data {
		keys = append(keys, k)
	}

	// 自定义排序函数
	sort.Slice(keys, func(i, j int) bool {
		return compare(data[keys[i]], data[keys[j]]) < 0
	})

	// 创建一个切片来存储排序后的字符串
	result = make([]string, 0, len(data))
	for _, k := range keys {
		result = append(result, k)
	}
	return
}

// compare 函数用于比较不同类型的值
func compare(a, b any) int {
	switch v1 := a.(type) {
	case int:
		switch v2 := b.(type) {
		case int:
			return v1 - v2
		case int64:
			if int64(v1) < v2 {
				return -1
			} else if int64(v1) > v2 {
				return 1
			}
		case float64:
			if float64(v1) < v2 {
				return -1
			} else if float64(v1) > v2 {
				return 1
			}
		}
	case int64:
		switch v2 := b.(type) {
		case int:
			if v1 < int64(v2) {
				return -1
			} else if v1 > int64(v2) {
				return 1
			}
		case int64:
			return int(v1 - v2)
		case float64:
			if float64(v1) < v2 {
				return -1
			} else if float64(v1) > v2 {
				return 1
			}
		}
	case float64:
		switch v2 := b.(type) {
		case int:
			if v1 < float64(v2) {
				return -1
			} else if v1 > float64(v2) {
				return 1
			}
		case int64:
			if v1 < float64(v2) {
				return -1
			} else if v1 > float64(v2) {
				return 1
			}
		case float64:
			if v1 < v2 {
				return -1
			} else if v1 > v2 {
				return 1
			}
		}
	}
	return 0
}

func GetJSONFieldNames(v interface{}) []string {
	var jsonFieldNames []string
	val := reflect.ValueOf(v)
	// 确保传入的是结构体
	if val.Kind() != reflect.Struct {
		return nil
	}
	typ := val.Type()
	for i := 0; i < val.NumField(); i++ {
		field := typ.Field(i)
		jsonTag := field.Tag.Get("json")
		if jsonTag != "" {
			jsonFieldNames = append(jsonFieldNames, jsonTag)
		}
	}
	return jsonFieldNames
}

func ErrAddPrintf(funcName string, err error) (err1 error) {
	var newFuncName = funcName
	if strings.HasPrefix(funcName, "[") && strings.HasSuffix(funcName, "]") {
		newFuncName = funcName[1 : len(funcName)-1]
	}
	return errors.New(fmt.Sprintf("func(%v) -> %v", newFuncName, err))
}
func SetFinalizer(manyValue any) {
	switch manyValue.(type) {
	case [][]*string:
		for _, v1 := range manyValue.([][]*string) {
			for _, v2 := range v1 {
				runtime.SetFinalizer(v2, nil)
			}
		}
	case []*string:
		for _, v1 := range manyValue.([]*string) {
			runtime.SetFinalizer(v1, nil)
		}
	case *string:
		runtime.SetFinalizer(manyValue, nil)
	}
}

// ReconstructionPath 重新创建目录
func ReconstructionPath(fullPath string) (bool, error) {
	if _, err := os.Stat(fullPath); os.IsNotExist(err) {
		// 如果路径不存在，则创建
		err = os.MkdirAll(fullPath, os.ModePerm)
		if err != nil {
			return false, err
		}
	} else {
		// 目录存在，删除并重新创建
		err = os.RemoveAll(fullPath)
		if err != nil {
			return false, err
		}
		err = os.MkdirAll(fullPath, os.ModePerm)
		if err != nil {
			return false, err
		}
	}
	return true, nil
}

// ReconPath 重新创建目录
func ReconPath(fullPath string) (bool, error) {
	if _, err := os.Stat(fullPath); os.IsNotExist(err) {
		// 如果路径不存在，则创建
		err = os.MkdirAll(fullPath, os.ModePerm)
		if err != nil {
			return false, err
		}
	}
	return true, nil
}

func stringNullActive(t any) (r any) {
	switch fmt.Sprintf("%v", t) {
	case "<null>", "<entry>", "<nil>":
		r = "NULL"
	default:
		r = fmt.Sprintf("%v", t)
	}
	return
}
func AnyToJsonString(s any) string {
	if q, err := json.Marshal(s); err != nil {
		return ""
	} else {
		return string(q)
	}
}
func StringAnyToInt64(s any) (res int64, err error) {
	defer func() {
		if r := RecoverPanic("StringAnyToInt64", recover()); err == nil && r != nil {
			err = r
		}
		if err != nil {
			err = ErrAddPrintf("stringAnyToInt64", err)
		}
	}()
	switch pp := stringNullActive(s); pp.(type) {
	case string:
		if !strings.EqualFold(pp.(string), "NULL") {
			return strconv.ParseInt(fmt.Sprintf("%v", pp), 10, 64)
		}
	default:
		err = errors.New(fmt.Sprintf("type is not match. curry type is %v", reflect.TypeOf(s)))
	}
	return
}
func StringAnyToFloat64(s any) (res float64, err error) {
	defer func() {
		if err != nil {
			err = ErrAddPrintf("stringAnyToInt64", err)
		}
	}()
	switch pp := stringNullActive(s); pp.(type) {
	case string:
		if !strings.EqualFold(pp.(string), "NULL") {
			return strconv.ParseFloat(fmt.Sprintf("%v", pp), 64)
		}
	default:
		err = errors.New(fmt.Sprintf("type is not match. curry type is %v", reflect.TypeOf(s)))
	}
	return
}
func MapNullActive(s map[string]any) (p map[string]any) {
	p = make(map[string]any)
	for q, t := range s {
		switch fmt.Sprintf("%v", t) {
		case "<null>", "<entry>":
			p[q] = "NULL"
		default:
			p[q] = fmt.Sprintf("%v", t)
		}
	}
	return
}
func StringGarthToMap(q []string) (r map[string]int) {
	r = make(map[string]int)
	for _, v := range q {
		r[v]++
	}
	return
}
func RecoverPanic(event string, r any) (err error) {
	if r != nil {
		// 获取并打印调用栈信息
		buf := make([]byte, 4096)
		n := runtime.Stack(buf, true)
		err = fmt.Errorf(string(buf[:n]))
		log.ErrorLog().ErrorS(event, fmt.Sprintf(" defer recover An exception was captured. panic is %v abnormal is %v:", r, err))
	}
	return
}

func CpuAnalyze() *os.File {
	// 创建 CPU 性能配置文件
	log.MainLog().Info("Enable CPU performance monitoring")
	f, err := os.Create("cpu.pprof")
	if err != nil {
		log.MainLog().Warn(fmt.Sprintf("Failed to create cpu monitoring file. error info is %v", err))
		return nil
	}
	// 开始 CPU 性能采样
	if err = pprof.StartCPUProfile(f); err != nil {
		log.MainLog().Warn(fmt.Sprintf("Failed to enable cpu performance monitoring. error info is %v", err))
		return nil
	}
	return f
}
func MemAnalyze() *os.File {
	// 创建一个文件来保存内存分析数据
	log.MainLog().Info("Enable Memory performance monitoring")
	f, err := os.Create("mem.prof")
	if err != nil {
		log.MainLog().Warn(fmt.Sprintf("Failed to create memory monitoring file. error info is %v", err))
		return nil
	}
	if err = pprof.WriteHeapProfile(f); err != nil {
		log.MainLog().Warn(fmt.Sprintf("Failed to enable memory performance monitoring. error info is %v", err))
		return nil
	}
	return f
}
